/*
若有错误代码C4996 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
在UDP客户端.cpp右键属性-C/C++-预处理器-预处理器定义中添加 _WINSOCK_DEPRECATED_NO_WARNINGS
*/
#include"pch.h"		//如果此头文件报错，将这个头文件删除即可
#include <stdio.h>
#include<iostream>
#include<WinSock2.h>
#include <string>
#include <iomanip>
#include<windows.h>
#include<Mmsystem.h>
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"ws2_32.lib")
using namespace std;

int main() {
	void ALARM();
	char *sendi(int, SOCKET, char*, sockaddr_in, int);
	char *receive(int, SOCKET, char *, sockaddr_in, int);
	//套接字信息结构
	WSADATA wsadata;
	//设置版本号
	WORD sockVersion = MAKEWORD(2, 2);
	//建立一个客户端套接字；
	SOCKET sClient;
	//启动构建，将“为ws2_32.lib”加载到内存中，做一些初始化工作
	if (WSAStartup(sockVersion, &wsadata) != 0) {
		//判断是否构建成功，若失败，则客户端打印一句提示话。
		printf("WSAStartup failed \n");
		return 0;
	}

	//创建客户端udp套接字
	sClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (SOCKET_ERROR == sClient) {
		printf("socket failed !\n");
		return 0;
	}

	//创建服务器端地址
	sockaddr_in serverAddr;
	//创建客户端端地址
	sockaddr_in clientAddr;
	//设置服务器端地址，端口号，协议族
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(8889);
	serverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	//获取服务器地址和客户端地址构造体的长度
	int slen = sizeof(serverAddr);
	int clen = sizeof(clientAddr);
	//设置接受数据缓冲区大小
	char buffer[1024];
	memset(buffer, 0, sizeof(buffer));
	//用于记录发送函数和接受函数的返回值
	int iSend = 0;
	int iRcv = 0;
	//string str;
	int x, n;

	cout << "开始与服务器建立通信..." << endl;
	cout << "请输入你要进行的操作，初始化请输入init，测温请输入read" << endl;

	while (1)
	{
		cout << "client:";
		cin >> buffer;
		sendi(iSend, sClient, buffer, serverAddr, slen);
		memset(buffer, 0, sizeof(buffer));

		iRcv = recvfrom(sClient, buffer, sizeof(buffer), 0, (SOCKADDR*)&clientAddr, &clen);
		if (iRcv == SOCKET_ERROR) {
			cout << "recvFrom failed " << endl;
			closesocket(sClient);
			WSACleanup();
			cout << "5s后关闭控制台。" << endl;
			Sleep(5000);
			return 0;
		}
		//判断服务器是否关闭
		if (iRcv <= 0) {
			cout << "server disconnected··· " << endl;
			closesocket(sClient);
			WSACleanup();
			cout << "5s后关闭控制台。" << endl;
			Sleep(5000);
			return 0;
		}
		else {
			cout << " Server: " << buffer << endl;
		}
		if (!strcmp(buffer, "初始化成功"))
			break;
		memset(buffer, 0, sizeof(buffer));
	}

	while (1)
	{
		memset(buffer, 0, sizeof(buffer));
		cout << "请输入你要进行的操作，初始化请输入init，测温请输入read:" << endl;
		cin >> buffer;
		sendi(iSend, sClient, buffer, serverAddr, slen);
		memset(buffer, 0, sizeof(buffer));

		iRcv = recvfrom(sClient, buffer, sizeof(buffer), 0, (SOCKADDR*)&clientAddr, &clen);
		if (iRcv == SOCKET_ERROR) {
			cout << "recvFrom failed " << endl;
			closesocket(sClient);
			WSACleanup();
			cout << "5s后关闭控制台。" << endl;
			Sleep(5000);
			return 0;
		}
		//判断服务器是否关闭
		if (iRcv <= 0) {
			cout << "server disconnected··· " << endl;
			closesocket(sClient);
			WSACleanup();
			cout << "5s后关闭控制台。" << endl;
			Sleep(5000);
			return 0;
		}
		else {
			cout << " Server: " << buffer << endl;
		}

		if (!strcmp(buffer, "未初始化"))
			continue;
		if (!strcmp(buffer, "初始化成功"))
			continue;
		if (!strcmp(buffer, "request error"))
			continue;

		memset(buffer, 0, sizeof(buffer));

		L1:
		cin >> buffer;
		x = buffer[0] - '0';;
		sendi(iSend, sClient, buffer, serverAddr, slen);
		memset(buffer, 0, sizeof(buffer));

		if (x == 1)
		{
			iRcv = recvfrom(sClient, buffer, sizeof(buffer), 0, (SOCKADDR*)&clientAddr, &clen);//从sensor得到temp
			cout << "实时监测模式，" << endl << "当前温度为：" << buffer << "℃" << endl;
			memset(buffer, 0, sizeof(buffer));
		}
		else if (x == 0)
		{
			iRcv = recvfrom(sClient, buffer, sizeof(buffer), 0, (SOCKADDR*)&clientAddr, &clen);//从sensor得到temp
			cout << " Server: " << buffer << endl;
			memset(buffer, 0, sizeof(buffer));
			cin >> buffer;
			n = buffer[0] - '0';
			sendi(iSend, sClient, buffer, serverAddr, slen);//将n传给sensor，并从sensor那里得到温度数组temp
			memset(buffer, 0, sizeof(buffer));
			cout << "24h内测得温度为：" << endl;
			for (int i = 0;i < n;i++)
			{
				iRcv = recvfrom(sClient, buffer, sizeof(buffer), 0, (SOCKADDR*)&clientAddr, &clen);
				cout << buffer << "℃" << ' ';
				iSend = sendto(sClient, buffer, strlen(buffer), 0, (SOCKADDR*)&serverAddr, slen);
				memset(buffer, 0, sizeof(buffer));
			}
			cout << endl;
		}
		else if (x == 2)
		{
			cout << "报警模式，请输入预警温度T（最大精度百分位）" << endl;
			float T,temp;
			cin >> T;
			
			iRcv = recvfrom(sClient, buffer, sizeof(buffer), 0, (SOCKADDR*)&clientAddr, &clen);
			cout << "预警温度：" << T << "℃" << endl << "当前温度：" << buffer << "℃" << endl;
			
			temp = atof(buffer);
			
			if (temp >= T)
			{
				cout << "高温！高温！" << endl;
				ALARM();//播放警报声
			}
		}
		else
		{
			iRcv = recvfrom(sClient, buffer, sizeof(buffer), 0, (SOCKADDR*)&clientAddr, &clen);
			cout << " Server: " << buffer << endl;
			goto L1;
		}

	}
	
	closesocket(sClient);
	WSACleanup();
	return 0;
}


void ALARM()//报警声
{
	PlaySound(TEXT("D:\\A.wav"), NULL, SND_FILENAME | SND_ASYNC);
	getchar();
}

char *sendi(int iSend, SOCKET sClient,char *buffer, sockaddr_in serverAddr, int slen)
{
	iSend = sendto(sClient, buffer, strlen(buffer), 0, (SOCKADDR*)&serverAddr, slen);
	if (iSend == SOCKET_ERROR) {
		cout << "sendto failed " << endl;
		closesocket(sClient);
		WSACleanup();
		cout << "5s后关闭控制台。" << endl;
		Sleep(5000);
		return 0;
	}
	//若数据为close，断开连接
	if (!(strcmp(buffer, "close"))) {
		cout << "close connection " << endl;
		closesocket(sClient);
		WSACleanup();
		cout << "5s后关闭控制它。" << endl;
		Sleep(5000);
		return 0;
	}
}

char *receive(int iRcv, SOCKET sClient, char *buffer, sockaddr_in clientAddr, int clen)
{
	iRcv = recvfrom(sClient, buffer, sizeof(buffer), 0, (SOCKADDR*)&clientAddr, &clen);
	if (iRcv == SOCKET_ERROR) {
		cout << "recvFrom failed " << endl;
		closesocket(sClient);
		WSACleanup();
		cout << "5s后关闭控制台。" << endl;
		Sleep(5000);
		return 0;
	}
	//判断服务器是否关闭
	if (iRcv <= 0) {
		cout << "server disconnected··· " << endl;
		closesocket(sClient);
		WSACleanup();
		cout << "5s后关闭控制台。" << endl;
		Sleep(5000);
		return 0;
	}
	else {
		cout << " Server: " << buffer << endl;
	}
	return buffer;
}

